#ifndef _PARSER_H_
#define _PARSER_H_

#include <vector>
#include <stdlib.h>
#include <string>
#include <fstream>
#include <iostream>
#include <sstream>
#include <set>
#include <map>

enum ParamType {NA = 0, GP, FP, CONST, ADDR_OFFSET, FIELD_OFFSET, LOCAL_VAR, REG, LABEL};

enum Operator {UNDEF = 0, NOP, ADD, SUB, MUL, DIV, MOD, NEG, CMPEQ, CMPLE, CMPLT, BR, BLBC, BLBS, CALL, LOAD, STORE, MOVE, READ, WRITE, WRL, PARAM, ENTER, RET, ENTRYPC, PHI};

using namespace std;

class Param {
public:
	ParamType type;
	int value;
	string literal;
	int var_id;

	Param() :
		type(NA), value(0), literal(), var_id(-1) {
	}

	Param(ParamType t, int val = 0, string str = "", int id = -1) {
		type = t;
		value = val;
		literal = str;
		var_id = id;
	}

	void set(ParamType t, int val = 0, string str = "") ;

	void parse(string s);

	void print(ostream&);


private:
	bool isNum(string s);
};

class Instr {
public:
	string sOpt;
	Operator opt;
	Param param1;
	Param param2;

	map<int, int> phi_param;

	Instr() :
		opt(NOP), param1(), param2(), sOpt(), phi_param() {
	}

	/*Instr(Operator op, const Param& p1 = Param(NA), const Param& p2 = Param(NA)) :
		opt(op) {
		param1 = p1;
		param2 = p2;
	}*/

	void parse(string s);

	Operator parseOpt(string o);

	void print(ostream&);
};

class IR {
public:
	vector<Instr> instructions;

	IR(istream& input) {
		instructions.clear();
		instructions.push_back(Instr());

		string buf;
		while (input.good()) {
			getline(input, buf);
			if (buf.size() <= 0)
				break;
			Instr instr;
			instr.parse(buf);
			instructions.push_back(instr);
		}
	}

	void print(ostream& );

	void refine();
};


#endif
